﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.Utilities;
using Microsoft.VisualStudio.Text.Tagging;
using Microsoft.VisualStudio.Text;
using Antlr.Runtime;
using System.Threading;
using LuaLanguageExtension.Parsing;
using LuaLanguageExtension;
using Microsoft.VisualStudio.Text.Classification;
using PSLib.Parsing.Common;
using PSLib.Parsing.Lua;
using PSLib.Parsing.Common.Search;

namespace LuaLanguageExtension.Tags
{
    internal sealed class Tagger : ITagger<ClassificationTag>, IDisposable 
    {
        internal Tagger(IObjectModelProviderBroker tokenStreamProviderBroker, ITextBuffer buffer, IClassificationTypeRegistryService typeService)
        {
            this.tokenStreamProvider = tokenStreamProviderBroker.GetProvider(buffer);
            this.tokenStreamProvider.TokenStreamChanged += new ObjectModelProvider.SnapshotEvent(tokenStreamProvider_TokenStreamChanged);

            foreach (var item in Enum.GetValues(typeof(RecognizedTokenType)))
            {
                if (!Constants.LuaTokenClassificationTypes.ContainsKey((RecognizedTokenType)item))
                {
                    IClassificationType clType = typeService.GetClassificationType("PSLib." + item.ToString());
                    Constants.LuaTokenClassificationTypes.Add((RecognizedTokenType)item, clType);
                }
            }
        }

        #region ITagger Members

        public IEnumerable<ITagSpan<ClassificationTag>> GetTags(NormalizedSnapshotSpanCollection spans)
        {
            foreach (SnapshotSpan curSpan in spans)
            {
                ITextSnapshotLine line = curSpan.Start.GetContainingLine();
                string lineText = line.GetText();

                foreach (var item in tokenStreamProvider.GetClassificationTags(curSpan))
                {
                    yield return item;
                } 
            }
        }

        public event EventHandler<SnapshotSpanEventArgs> TagsChanged;

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            this.tokenStreamProvider.Dispose();
        }

        #endregion

        #region Event Handlers

        private void tokenStreamProvider_TokenStreamChanged(SnapshotSpan snapshotSpan)
        {
            if (TagsChanged != null) TagsChanged(this, new SnapshotSpanEventArgs(snapshotSpan));
        }

        #endregion

        private ObjectModelProvider tokenStreamProvider;

       
    }
}
